package projectmanagement.managementtool.IterationServices;

import projectmanagement.managementtool.IdGenerator;
import projectmanagement.models.Iteration;
import projectmanagement.models.Project;

import java.util.Calendar;
import java.util.Collection;
import java.util.List;

/**
 * IterationServiceImpl provides concrete implementation of
 * functionality for IterationService and is intended to
 * handle all iterations-related logic.
 *
 * @author Dmitry Shvets
 */
public class IterationServiceImpl implements IterationService {

    public static final int MAX_DURATION_DAYS = 365;

    public Iteration createIteration(Project project, Calendar startDate, Calendar finishDate, String description) {
        int duration = daysBetween(startDate, finishDate);
        if (isTimingValid(project, startDate, finishDate, duration)) {
            Iteration iteration = new Iteration(startDate, finishDate, duration, description);
            iteration.setId(IdGenerator.generate(iteration.getClass()));
            project.addIteration(iteration);
            return iteration;
        }
        return null;
    }

    public int scheduleIterations(Project project, int duration) {
        Calendar iterationFinish = (Calendar) project.getProjectStartDate().clone();
        iterationFinish.add(Calendar.DAY_OF_YEAR, duration);
        Calendar projectFinish = project.getProjectFinishDate();
        int numberOfIterationsAdded = 0;
        List<Iteration> iterations = project.getIterationList();
        iterations.clear();
        while (projectFinish.after(iterationFinish)) {
            Iteration iteration = new Iteration(duration, "Automatically scheduled iteration.");
            iteration.setId(IdGenerator.generate(iteration.getClass()));
            project.addIteration(iteration);
            iterationFinish.add(Calendar.DAY_OF_YEAR, duration);
            numberOfIterationsAdded++;
        }
        return numberOfIterationsAdded;
    }

    public Collection<Iteration> getListOfIterations(Project project) {
        return project.getIterationList();
    }

    public Iteration getIterationById(Project project, int iterationId) {
        Collection<Iteration> iterations = project.getIterationList();
        for (Iteration currentIteration : iterations) {
            if (currentIteration.getId() == iterationId)
                return currentIteration;
        }
        return null;
    }

    public boolean isTimingValid(Project project, Calendar startDate, Calendar finishDate, int duration) {
        if (project.getProjectStartDate().after(startDate))
            return false;
        if (project.getProjectFinishDate().before(finishDate))
            return false;
        return (duration >= 1) && (duration <= MAX_DURATION_DAYS);
    }

    public boolean isTimingValid(Project project, Calendar startDate, Calendar finishDate) {
        int duration = daysBetween(startDate, finishDate);
        return this.isTimingValid(project, startDate, finishDate, duration);
    }

    public int getLastId() {
        return IdGenerator.getLastId(Iteration.class);
    }

    private static int daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        int daysBetween = 0;
        while ((date.before(endDate)) && (daysBetween <= MAX_DURATION_DAYS + 1)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }

}